import Package from '@start-cli-dev/package'
import log from '@start-cli-dev/log'
import path from 'path'
import cp from 'child_process'
// 手动维护一个配置表 根据命令 对应到npm 包名 （后期维护可以防盗服务器上从服务器拉去）
const SETTINGS: Record<string, string> = {
  init: '@start-cli-dev/init'
}
const CACHE_DIR = 'dependencies'

// spawn 兼容windows
function spawn(
  command: string,
  args: readonly string[],
  options: cp.SpawnOptions
) {
  const win32 = process.platform === 'win32'
  const cmd = win32 ? 'cmd' : command
  const cmdArgs = win32 ? ['/c'].concat(command, args) : args
  return cp.spawn(cmd, cmdArgs, options)
}

export default async function exec(...args: any[]) {
  let targetPath = process.env.CLI_TARGET_PATH as string
  const homePath = process.env.CLI_HOME_PATH as string

  let storeDir = ''
  let pkg

  const cmdObj = args[args.length - 1] // 最后一个参数是命令对象program

  const cmdName: string = cmdObj.name()
  const packageName = SETTINGS[cmdName]
  const packageVersion = 'latest'
  if (!targetPath) {
    targetPath = path.resolve(homePath, CACHE_DIR)
    storeDir = path.resolve(targetPath, 'node_modules')
    pkg = new Package({
      targetPath,
      storeDir,
      packageName,
      packageVersion
    })
    if (await pkg.exists()) {
      // 更新package
      await pkg.update()
    } else {
      // 安装package
      await pkg.install()
    }
  } else {
    pkg = new Package({
      targetPath,
      storeDir,
      packageName,
      packageVersion
    })
  }

  log.verbose('targetPath', targetPath)
  log.verbose('storeDir', storeDir)

  const rootFile = pkg.getRootFilePath() as string
  if (rootFile) {
    const cmd = args[args.length - 1]
    const o = Object.create(null)
    Object.keys(cmd).forEach(key => {
      // eslint-disable-next-line no-prototype-builtins
      if (cmd.hasOwnProperty(key) && !key.startsWith('_') && key !== 'parent') {
        o[key] = cmd[key]
      }
    })
    // eslint-disable-next-line no-param-reassign
    args[args.length - 1] = o
    const code = `(async () => {
        const init =(await import('${rootFile}')).default;
        try{
          init(${JSON.stringify(args)})
        }catch(e){
          log.error('', e .message)
        }
      })();`
    const child = spawn('node', ['-e', code], {
      stdio: 'inherit'
    })
    child.on('error', e => {
      log.error('', e.message)
      process.exit(1)
    })
    child.on('exit', e => {
      log.verbose('', `命令执行成功${e}`)
      process.exit(e as number)
    })
  }
}
